package com.wqs.tool.datainit.util;

import java.io.IOException;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.DynaBean;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.wqs.tool.datainit.common.DataTypeEnum;
import com.wqs.tool.datainit.entity.DataBase;
import com.wqs.tool.datainit.entity.Mapper;
import com.wqs.tool.datainit.entity.Task;


/**
 * 数据操作工具
 * @author ALEX
 *
 */
public class DataOprationUtils {
	
	/**
	 * 操作 task 中type = 1 的数据
	 */
	public static void oprationTypeOne(RedisUtils redis,Task task) {
		boolean exist = redis.hasKey(task.getRedisKey());
		if(exist) {
			redis.del(task.getRedisKey());
		}
		redis.set(task.getRedisKey(), task.getRedisValue());
	}
	
	
	
	/**
	 * 操作 task 中type = 2 的数据
	 */
	public static void oprationTypeTwo(RedisUtils redis,Task task) {
		
		boolean exist = redis.hasKey(task.getRedisKey());
		if(exist) {
			redis.del(task.getRedisKey());
		}
		
		Map<String,Class> map = new HashMap<String,Class>();
		Map<Object,Object> valueMap = new HashMap<Object,Object>();
 		DataBase db = task.getDataBase();
		List<Object> list = new ArrayList<Object>();
		if(db !=null) {
			List<Mapper> mappers =db.getMappers();
			if(mappers!=null && mappers.size()>0) {
				for (Mapper mapper : mappers) {
					if("int".equals(mapper.getType())) {
						map.put(mapper.getField(), Integer.class);
					}else if("string".equals(mapper.getType())) {
						map.put(mapper.getField(), String.class);
					}else if("double".equals(mapper.getType())) {
						map.put(mapper.getField(), Double.class);
					}else if("long".equals(mapper.getType())) {
						map.put(mapper.getField(), Long.class);
					}
				}
			}
			
			// 1.获得数据库连接
			Connection conn = JdbcUtils.getConnection(task.getDataBase().getDriverClassName(),
					task.getDataBase().getUrl(), task.getDataBase().getUsername(),
					task.getDataBase().getPassword());
			// 2.查询
			List<DynaBean> rowlist = JdbcUtils.queryList(conn, task.getDataBase().getSqlSentence());
			
			if(rowlist!=null && rowlist.size()>0) {
				for (DynaBean row : rowlist){
					DynamicBean bean = new DynamicBean(map,task.getDataBase().getClassName());
					if(mappers!=null && mappers.size()>0) {
						for (Mapper mapper : mappers) {
							bean.setValue(mapper.getField(), row.get(mapper.getName()));
						}
					}
					if(DataTypeEnum.HASH.getType().equals(task.getDataType())) {
						valueMap.put(String.valueOf(bean.getValue(task.getHashKeyField())),bean.getObject());
					}else {
						list.add(bean.getObject());
					}
				
				}
			}
			switch(task.getDataType()) {
				case "string" :
					String json = CommonUtils.gson.toJson(list);
					//保持到redis
					redis.set(task.getRedisKey(), json);
					break;
				case "list" :
					redis.lSet(task.getRedisKey(), list);
					break;
				case "set" :
					redis.sSet(task.getRedisKey(), list.toArray());
					break;
				case "hash" :
					redis.hmset(task.getRedisKey(), valueMap);
					break;
			}
		}
		
	}
	
	
	
	/**
	 * 操作 task 中type = 3 的数据
	 */
	public static void oprationTypeThree(RedisUtils redis,Task task) {
		
		
		//存储类型 hash set
		String storageType = task.getStorageType();
		
		
		Map<String,Class> map = new HashMap<String,Class>();
		
		DataBase db = task.getDataBase();
		
		List<Map<Object,Object>> list = new ArrayList<Map<Object,Object>>();
		//解析数据库字段
		if(db !=null) {
			List<Mapper> mappers =db.getMappers();
			
			if(mappers!=null && mappers.size()>0) {
				for (Mapper mapper : mappers) {
					if("int".equals(mapper.getType())) {
						map.put(mapper.getField(), Integer.class);
					}else if("string".equals(mapper.getType())) {
						map.put(mapper.getField(), String.class);
					}else if("double".equals(mapper.getType())) {
						map.put(mapper.getField(), Double.class);
					}else if("long".equals(mapper.getType())) {
						map.put(mapper.getField(), Long.class);
					}
				}
			}
			
			
			// 1.获得数据库连接
			Connection conn = JdbcUtils.getConnection(task.getDataBase().getDriverClassName(),
								task.getDataBase().getUrl(), task.getDataBase().getUsername(),
								task.getDataBase().getPassword());
			// 2.查询
			List<DynaBean> rowlist = JdbcUtils.queryList(conn, task.getDataBase().getSqlSentence());
			
			//封装动态类
			if(rowlist!=null && rowlist.size()>0) {
				
				for (DynaBean row : rowlist){
					
					Mapper hasSplitMapper = hasSplit(mappers);
					
					if(hasSplitMapper != null) {
						//找到要分割的字段的值
						String velue = (String) row.get(hasSplitMapper.getName());
						if(velue != null) {
							List<String> splitList = null;
							try {
								splitList = CommonUtils.mapper.readValue(velue,new TypeReference<List<String>>() {});
							} catch (JsonParseException e) {
								e.printStackTrace();
							} catch (JsonMappingException e) {
								e.printStackTrace();
							} catch (IOException e) {
								e.printStackTrace();
							}
							
							if(splitList != null && splitList.size() > 0) {
								for (String str : splitList) {
									DynamicBean bean = new DynamicBean(map,task.getDataBase().getClassName());
									if(mappers!=null && mappers.size()>0) {
										for (Mapper mapper : mappers) {
											if(mapper.getName().equals(hasSplitMapper.getName())) {
												bean.setValue(mapper.getField(), str);
											}else {
												bean.setValue(mapper.getField(), row.get(mapper.getName()));
											}
										}
										
										Map<Object,Object> objMap = CommonUtils.mapper.convertValue(bean.getObject(),HashMap.class);
										
										list.add(objMap);
										
									}
								}
							}
						}
						
						
						
						
					}else {
						DynamicBean bean = new DynamicBean(map,task.getDataBase().getClassName());
						if(mappers!=null && mappers.size()>0) {
							for (Mapper mapper : mappers) {
								bean.setValue(mapper.getField(), row.get(mapper.getName()));
							}
							
							Map<Object,Object> objMap = CommonUtils.mapper.convertValue(bean.getObject(),HashMap.class);
							
							list.add(objMap);
							
						}
					}
				}
			}
			
			//解析rediskey 
			String redisKey = task.getRedisKey();
			if(!redisKey.contains("$")) {//不饱和$符合
				deleteKey(redis,redisKey);
				redis.lSet(redisKey, list);
				
			}else {
				
				if(DataTypeEnum.HASH.getType().equals(storageType)) { //hash
					for (Map<Object,Object> m : list) {
						String key = getKey(redisKey,m);
						deleteKey(redis,key);
						redis.hmset(key,m);
					}
					
				}else if(DataTypeEnum.SET.getType().equals(storageType)) { //set
					
					Map<String, List<String>> setMap = new HashMap<>();
					for (Map<Object, Object> m : list) {
						String key = getKey(redisKey,m);
						List<String> mapList = null;
						if(setMap.get(key) == null) {
							mapList = new ArrayList<>();
						}else {
							mapList = setMap.get(key);
						}
						mapList.add(CommonUtils.gson.toJson(m));
						setMap.put(key, mapList);
					}
					
					if(setMap !=null && setMap.size() > 0 ) {
						for (String  key : setMap.keySet()) {
							deleteKey(redis,key);
							redis.sSet(key, setMap.get(key).toArray());
						}
					}
					
					
				}
			
			}
		
		}
		
	}
	
	
	
	public static Mapper hasSplit(List<Mapper> mappers) {
		Mapper result = null;
		if(mappers == null) {
			return null;
		}
		for (Mapper mapper : mappers) {
			if(mapper.getSplit() != null) {
				result =  mapper;
				break;
			}
		}
		return result;
	}
	
	
	
	
	
	
	
	
	public static void deleteKey(RedisUtils redis,String key) {
		boolean exist = redis.hasKey(key);
		if(exist) {
			redis.del(key);
		}
	}
	
	
	public static String getKey(String redisKey,Map<Object,Object> map) {
		String [] str = redisKey.split(":");
		StringBuilder key = new StringBuilder();
		for (int i = 0; i < str.length; i++) {
			if(i == str.length - 1) {//last
				if(str[i].startsWith("$")) {
					key.append(map.get(str[i].replace("$", "")));
				}else {
					key.append(str[i]);
				}
			}else {
				if(str[i].startsWith("$")) {
					key.append(map.get(str[i].replace("$", ""))).append(":");
				}else {
					key.append(str[i]).append(":");
				}
			}
		}
		return key.toString();
	}
	
	
}
